import { postGetalljobtypes } from "@/apis/endpoint/home";
import { JobType } from "@/apis/endpoint/model";
import GpContainer from "@/components/GpContainer";
import { GpSearchInput } from "@/components/GpSeachInput";
import GpVerticelLine from "@/components/GpVerticelLine";
import { useNavigateEventChannel } from "@/hooks/useNavigateEventChannel";
import { withCache } from "@/utils/cache";
import { debounce } from "@/utils/helper";
import { navigate } from "@/utils/navigation";
import { ScrollView, Text, View } from "@tarojs/components";
import { useRouter } from "@tarojs/taro";
import clsx from "clsx";
import React, { useCallback, useEffect, useRef, useState } from "react";

type JobEntry = JobType & {
  root?: {id: number; name: string}
  parent?: {id: number; name: string}
}
type JobGroup = Expandable<JobEntry>
type JobGroupMap = {
  [rid: number]: JobGroup
}

type SearchItem = {
  node: React.ReactNode
  item: JobEntry
}

type RouteParams = {
  jobtypeid?: string
}
export default function Index() {
  const jobtypeId = Number(useRouter<RouteParams>().params.jobtypeid)
  const { eventChannel } = useNavigateEventChannel()
  const [rootNodes, setRootNodes] = useState<JobType[]>([])
  const availableJobs = useRef<JobEntry[]>([])
  const jobGroupMap = useRef<JobGroupMap>({})
  const [currentJobGroup, setCurrentJobGroup] = useState<JobGroup>()
  const [search, setSearch] = useState("")
  const [searchList, setSearchList] = useState<SearchItem[]>([])
  const triggerSearch = useCallback(debounce(300, (value: string) => {
    const text = value.trim()
    if (text.length === 0) {
      setSearchList([])
      return;
    }
    const regEx = new RegExp(`(${text})`, "i");
    const nodes = availableJobs.current
    .filter(item => regEx.test(item.name))
    .map(item => {
      const spliter = React.createElement(Text, {
        className: "text-theme"
      }, text)
      const parts = item.name.split(regEx).map<React.ReactNode>(part => {
        if (part === text) return spliter
        return part
      })
      return {
        node: parts,
        item
      }
    })
    setSearchList(nodes)
  }), [rootNodes])
  useEffect(() => {
    withCache("postGetalljobtypes", () => postGetalljobtypes().send())
    .then(list => {
      const roots: JobType[] = []
      const parents: JobType[] = []
      list.forEach(item => {
        if (item.level === 0) {
          roots.push(item)
        } else if (item.level === 1) {
          parents.push(item)
        } else {
          availableJobs.current.push(item)
        }
      })
      let activeRootId = 0
      for (let i = 0; i < roots.length; i++) {
        const r = roots[i]
        jobGroupMap.current[r.id] ??= {
          item: r,
          children: []
        }
        for (let j = 0; j < parents.length; j++) {
          const p = parents[j]
          if (r.id === p.parentId) {
            const group: JobGroup = {
              item: p,
              children: []
            }
            for (let k = 0; k < availableJobs.current.length; k++) {
              const l = availableJobs.current[k]
              if (p.id === l.parentId) {
                l.root = { id: r.id, name: r.name }
                l.parent = { id: p.id, name: p.name }
                group.children.push({
                  item: l,
                  children: []
                })
                if (jobtypeId && activeRootId === 0 && jobtypeId === l.id) {
                  activeRootId = r.id
                }
              }
            }
            jobGroupMap.current[r.id].children.push(group)
          }
        }
      }
      setCurrentJobGroup(jobGroupMap.current[activeRootId || roots[0].id])
      setRootNodes(roots)
    })
  }, [])
  function handleSearchChange(value: string) {
    setSearch(value)
    triggerSearch(value)
  }
  function handleTapItem(item: JobEntry) {
    process.env.NODE_ENV === "development" && console.log('选择了职位:', item)
    if (eventChannel) {
      eventChannel.emit("chooseJobType", item)
    }
    navigate()
  }
  function renderJobList() {
    return (
      <View className="flex-1 h-0 box-border flex flex-row items-stretch">
        <View className="h-full w-[252px] flex-none bg-[#F4F6FC]">
          <ScrollView
            style={{height: "100%"}}
            scrollY
            scrollWithAnimation
          >
            {
              rootNodes.map(item => (
                <View key={item.id} className={clsx("flex flex-row items-center relative box-border w-full h-[100px] pl-[32px] pr-[28px]", {
                  "bg-white": item.id === currentJobGroup?.item.id
                  })}
                  onClick={() => setCurrentJobGroup(jobGroupMap.current[item.id])}
                >
                  {
                    item.id === currentJobGroup?.item.id
                    ? <GpVerticelLine width={8} height={64} className="rounded-[4px] absolute left-0 my-auto" />
                    : null
                  }
                  <Text className={clsx("text-[28px]", item.id === currentJobGroup?.item.id ? "text-theme font-bold" : "text-primary font-normal")}>
                    {item.name}
                  </Text>
                </View>
              ))
            }
          </ScrollView>
        </View>
        <View className="h-full flex-1 w-0 bg-white">
          <ScrollView
            style={{height: "100%"}}
            scrollY
            scrollWithAnimation
          >
            {
              currentJobGroup?.children.map(p => (
                <View key={p.item.id} className="box-border px-[32px] mb-[64px]">
                  <View className="h-[100px] flex items-center text-primary font-bold text-[28px]">
                    {p.item.name}
                  </View>
                  <View className="grid grid-cols-2 gap-[18px] mt-[32px]">
                    {
                      p.children.map(l => (
                        <View key={l.item.id} onClick={() => handleTapItem(l.item)}
                        className={clsx("flex flex-row justify-center items-center rounded-[16px] px-[8px] py-[24px]", jobtypeId && jobtypeId === l.item.id ? "bg-theme/8 text-theme font-bold" : "bg-[#F7F8FA] text-primary")}>
                          <Text className="text-[28px] text-center">
                            {l.item.name}
                          </Text>
                        </View>
                      ))
                    }
                  </View>
                </View>
              ))
            }
          </ScrollView>
        </View>
      </View>
    )
  }
  function renderSearchList() {
    return (
      <View className="box-border px-[32px] flex-1 h-0 overflow-y-auto">
        {
          searchList.map(item => (
            <View onClick={() => handleTapItem(item.item)} className="flex flex-col gap-[16px] justify-center h-[138px] text-primary text-[32px] border-b-2 border-solid border-b-[#EEEEEE]">
              <Text>{item.node}</Text>
              <Text className="text-third text-[24px]">{item.item.root?.name}-{item.item.parent?.name}-{item.item.name}</Text>
            </View>
          ))
        }
      </View>
    )
  }
  return (
    <GpContainer className="bg-white box-border h-screen flex flex-col">
      <View className="px-[32px] pb-[24px] flex flex-col flex-none">
        <Text className="text-primary font-bold text-[48px] leading-[48px] pt-[20px]">想找什么工作？</Text>
        <GpSearchInput
          className="mt-[32px]"
          placeholder="搜索职位名称"
          value={search}
          onChange={handleSearchChange}
        />
      </View>
      { searchList.length > 0 ? renderSearchList() : renderJobList() }
    </GpContainer>
  )
}
